/**
 * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.jeeplus.modules.fee.web;

import com.google.common.collect.Lists;
import com.jeeplus.common.config.Global;
import com.jeeplus.common.json.AjaxJson;
import com.jeeplus.common.utils.DateUtils;
import com.jeeplus.common.utils.MyBeanUtils;
import com.jeeplus.common.utils.PrimaryGenerater;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.common.utils.excel.ExportExcel;
import com.jeeplus.common.utils.excel.ImportExcel;
import com.jeeplus.core.mapper.JsonMapper;
import com.jeeplus.core.persistence.Page;
import com.jeeplus.core.web.BaseController;
import com.jeeplus.modules.fee.entity.Consignor;
import com.jeeplus.modules.fee.entity.OpenInvoice;
import com.jeeplus.modules.fee.entity.OpenInvoiceDetail;
import com.jeeplus.modules.fee.entity.Receivables;
import com.jeeplus.modules.fee.service.ConsignorService;
import com.jeeplus.modules.fee.service.OpenInvoiceDetailService;
import com.jeeplus.modules.fee.service.OpenInvoiceService;
import com.jeeplus.modules.fee.service.ReceivablesService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 应开发票Controller
 * @author weisong
 * @version 2017-09-22
 */
@Controller
@RequestMapping(value = "${adminPath}/fee/openInvoice")
public class OpenInvoiceController extends BaseController {

	@Autowired
	private OpenInvoiceService openInvoiceService;
	@Autowired
	private ReceivablesService receivablesService;
	@Autowired
	private OpenInvoiceDetailService openInvoiceDetailService;
	@Autowired
	private ConsignorService consignorService;

	@ModelAttribute
	public OpenInvoice get(@RequestParam(required=false) String id) {
		OpenInvoice entity = null;
		if (StringUtils.isNotBlank(id)){
			entity = openInvoiceService.get(id);
		}
		if (entity == null){
			entity = new OpenInvoice();
		}
		return entity;
	}
	
	/**
	 * 应开发票列表页面
	 */
	@RequiresPermissions("fee:openInvoice:list")
	@RequestMapping(value = {"list", ""})
	public String list() {
		return "modules/fee/openInvoiceList";
	}
	
		/**
	 * 应开发票列表数据
	 */
	@ResponseBody
	@RequiresPermissions("fee:openInvoice:list")
	@RequestMapping(value = "data")
	public Map<String, Object> data(OpenInvoice openInvoice, HttpServletRequest request, HttpServletResponse response, Model model) {
		Page<OpenInvoice> page = openInvoiceService.findPage(new Page<OpenInvoice>(request, response), openInvoice); 
		return getBootstrapData(page);
	}

	/**
	 * 查看，增加，编辑应开发票表单页面
	 */
	@RequiresPermissions(value={"fee:openInvoice:view","fee:openInvoice:add","fee:openInvoice:edit"},logical=Logical.OR)
	@RequestMapping(value = "form")
	public String form(OpenInvoice openInvoice, Model model) {
		model.addAttribute("openInvoice", openInvoice);
		if(StringUtils.isBlank(openInvoice.getId())){//如果ID是空为添加
			model.addAttribute("isAdd", true);
		}
		List<OpenInvoiceDetail> list = openInvoiceDetailService.findOpenInvoiceDetailById(openInvoice.getId());
		if (null != list && list.size() > 0) {
			model.addAttribute("list", list);
			model.addAttribute("sign", "invoice");
		}
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		model.addAttribute("target",request.getParameter("target"));
		//来自发票form页面查看的标记
		String different = request.getParameter("different");
		if (null != different && different != "") {
			model.addAttribute("different", different);
		}
		return "modules/fee/openInvoiceForm";
	}

	/**
	 * 保存应开发票
	 */
	@RequiresPermissions(value={"fee:openInvoice:add","fee:openInvoice:edit"},logical=Logical.OR)
	@RequestMapping(value = "save")
	public String save(OpenInvoice openInvoice, Model model, RedirectAttributes redirectAttributes, HttpServletRequest request) throws Exception{
		if (!beanValidator(model, openInvoice)){
			return form(openInvoice, model);
		}
		if(!openInvoice.getIsNewRecord()){//编辑表单保存
			OpenInvoice t = openInvoiceService.get(openInvoice.getId());//从数据库取出记录的值
			MyBeanUtils.copyBeanNotNull2Bean(openInvoice, t);//将编辑表单中的非NULL值覆盖数据库记录中的值
			openInvoiceService.save(t);//保存
			// 保存到发票明细表
			String ids = request.getParameter("ids"); // 将form页面取的id值循环遍历123_500
			// 保存到发票明细表
			if(StringUtils.isNotEmpty(ids)){
				saveOpenInvoiceDetail(ids,openInvoice);
			}
			addMessage(redirectAttributes, "保存应开发票成功");
		}else {//新增表单保存
			String ids= request.getParameter("ids");	//将form页面取的id值循环遍历
			if (StringUtils.isEmpty(ids) || StringUtils.isEmpty(ids.trim().replaceAll(",",""))) {
				addMessage(redirectAttributes, "请引入发票明细表");
			} else {
				//生成单号
				String number = "";
				OpenInvoice pay = openInvoiceService.findInvoiceNoAndInvoiceDate();
				Format format1 = new SimpleDateFormat("yyyyMMdd");    //初始化时间格式
				//比较结算日期是否和现在的日期相等
				if (null == pay) {
					number = PrimaryGenerater.getInstance().generaterNextNumber("YKFP", null);
				} else {
					if (String.valueOf(format1.format(pay.getInvoiceDate())).equals(String.valueOf(format1.format(new Date())))) {
						number = PrimaryGenerater.getInstance().generaterNextNumber("YKFP", pay.getInvoiceNo());
					} else {
						number = PrimaryGenerater.getInstance().generaterNextNumber("YKFP", null);
					}
				}
				openInvoice.setInvoiceNo(number);
				String[] _ids = ids.split(","); // 将form页面取的id值循环遍历
				String receIds = "";
				//获取应收结算单id
				if(_ids.length>0){
					for (String id : _ids) {
						if (StringUtils.isNotEmpty(id)) {
							String [] tempRece = id.split("_"); // 123_200
							if(tempRece.length>0){
								receIds += tempRece[0]+",";
							}
						}
					}
				}
				openInvoice.setFeeReceivables(receIds);
				openInvoiceService.save(openInvoice);//保存

				// 保存到发票明细表
				if(StringUtils.isNotEmpty(ids)){
					saveOpenInvoiceDetail(ids,openInvoice);
				}
				addMessage(redirectAttributes, "保存应开发票成功");
				String type = request.getParameter("typeTarget");
				System.out.println(type);
				if(null != type){
					if(type.equals("ableList")) {
						return "redirect:" + Global.getAdminPath() + "/fee/receivables/?repage";
					}else{
						return "redirect:" + Global.getAdminPath() + "/fee/openInvoice/?repage";
					}
				}
			}
		}
		return "redirect:"+Global.getAdminPath()+"/fee/openInvoice/?repage";
	}
	
	/**
	 * 删除应开发票
	 */
	@ResponseBody
	@RequiresPermissions("fee:openInvoice:del")
	@RequestMapping(value = "delete")
	public AjaxJson delete(OpenInvoice openInvoice, RedirectAttributes redirectAttributes) {
		AjaxJson j = new AjaxJson();
		openInvoiceService.delete(openInvoice);
		j.setMsg("删除应开发票成功");
		return j;
	}
	
	/**
	 * 批量删除应开发票
	 */
	@ResponseBody
	@RequiresPermissions("fee:openInvoice:del")
	@RequestMapping(value = "deleteAll")
	public AjaxJson deleteAll(String ids, RedirectAttributes redirectAttributes) {
		AjaxJson j = new AjaxJson();
		String idArray[] =ids.split(",");
		for(String id : idArray){
			//根据应收发票id查询应付发票明细表
			OpenInvoiceDetail openInvoiceDetail = new OpenInvoiceDetail();
			openInvoiceDetail.setFeeOpenInvoice(openInvoiceService.get(id));
			List<OpenInvoiceDetail> list = openInvoiceDetailService.findList(openInvoiceDetail);
			for (int i = 0; i < list.size(); i++) {
				//删除应收发票明细表
				openInvoiceDetailService.delete(list.get(i));
			}
			openInvoiceService.delete(openInvoiceService.get(id));
		}
		j.setMsg("删除应开发票成功");
		return j;
	}
	
	/**
	 * 导出excel文件
	 */
	@ResponseBody
	@RequiresPermissions("fee:openInvoice:export")
    @RequestMapping(value = "export", method=RequestMethod.POST)
    public AjaxJson exportFile(OpenInvoice openInvoice, HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) {
		AjaxJson j = new AjaxJson();
		try {
            String fileName = "应开发票"+DateUtils.getDate("yyyyMMddHHmmss")+".xlsx";
            Page<OpenInvoice> page = openInvoiceService.findPage(new Page<OpenInvoice>(request, response, -1), openInvoice);
    		new ExportExcel("应开发票", OpenInvoice.class).setDataList(page.getList()).write(response, fileName).dispose();
    		j.setSuccess(true);
    		j.setMsg("导出成功！");
    		return j;
		} catch (Exception e) {
			j.setSuccess(false);
			j.setMsg("导出应开发票记录失败！失败信息："+e.getMessage());
		}
			return j;
    }

	/**
	 * 导入Excel数据

	 */
	@RequiresPermissions("fee:openInvoice:import")
    @RequestMapping(value = "import", method=RequestMethod.POST)
    public String importFile(MultipartFile file, RedirectAttributes redirectAttributes) {
		try {
			int successNum = 0;
			int failureNum = 0;
			StringBuilder failureMsg = new StringBuilder();
			ImportExcel ei = new ImportExcel(file, 1, 0);
			List<OpenInvoice> list = ei.getDataList(OpenInvoice.class);
			for (OpenInvoice openInvoice : list){
				try{
					openInvoiceService.save(openInvoice);
					successNum++;
				}catch(ConstraintViolationException ex){
					failureNum++;
				}catch (Exception ex) {
					failureNum++;
				}
			}
			if (failureNum>0){
				failureMsg.insert(0, "，失败 "+failureNum+" 条应开发票记录。");
			}
			addMessage(redirectAttributes, "已成功导入 "+successNum+" 条应开发票记录"+failureMsg);
		} catch (Exception e) {
			addMessage(redirectAttributes, "导入应开发票失败！失败信息："+e.getMessage());
		}
		return "redirect:"+Global.getAdminPath()+"/fee/openInvoice/?repage";
    }
	
	/**
	 * 下载导入应开发票数据模板
	 */
	@RequiresPermissions("fee:openInvoice:import")
    @RequestMapping(value = "import/template")
    public String importFileTemplate(HttpServletResponse response, RedirectAttributes redirectAttributes) {
		try {
            String fileName = "应开发票数据导入模板.xlsx";
    		List<OpenInvoice> list = Lists.newArrayList(); 
    		new ExportExcel("应开发票数据", OpenInvoice.class, 1).setDataList(list).write(response, fileName).dispose();
    		return null;
		} catch (Exception e) {
			addMessage(redirectAttributes, "导入模板下载失败！失败信息："+e.getMessage());
		}
		return "redirect:"+Global.getAdminPath()+"/fee/openInvoice/?repage";
    }

	/**
	 * 获取弹出窗口的数据
	 */
	@RequestMapping(value = "findReceiveList")
	public @ResponseBody
	List<Receivables> findReceiveList(Receivables feeReceivables, HttpServletRequest request, HttpServletResponse response) {
		// 判断应付结算单的状态【已确认，部分开票，部分核销】
		String _status = request.getParameter("status");
		//获取查询框输入的值[模糊查询]
		String clearUnit = request.getParameter("clearUnit");
		if (_status != null) {
			Integer status = Integer.parseInt(_status);
			feeReceivables.setStatus(status);
		}
		if (StringUtils.isNotEmpty(clearUnit)) {
			Consignor f = new Consignor();
			f.setName(clearUnit);
			feeReceivables.setPayerName(f);//结算方
		}
		List<Receivables> list = receivablesService.findList(feeReceivables);
		return list;
	}

	/**
	 * 保存发票子表
	 */
	public void saveOpenInvoiceDetail(String ids,OpenInvoice openInvoice){
		// 保存到发票明细表
		OpenInvoiceDetail oid = null;
		String[] _ids = ids.split(","); // 将form页面取的id值循环遍历123_500
		String[] str = null;
		if (_ids.length != 0) {
			for (String id : _ids) {
				if (StringUtils.isNotEmpty(id)) {
					oid = new OpenInvoiceDetail();
					str = id.split("_"); // 123 200
					if (StringUtils.isNotEmpty(str[0])) {
						Receivables receivables = receivablesService.get(str[0]);
						oid.setFeeReceivables(receivables);
						oid.setClearingNo(receivables.getClearingNo());
						oid.setPayMoney(receivables.getPayMoney());
						if (null == receivables.getInvoiceMoney()) {
							oid.setInvoiceMoney(0.0);
						} else {
							oid.setInvoiceMoney(receivables.getInvoiceMoney());
						}
					}
					if (StringUtils.isNotEmpty(str[1])) {
						oid.setInvMoney(Double.parseDouble(str[1]));
					}
					oid.setFeeOpenInvoice(openInvoice);
					openInvoiceDetailService.save(oid);
				}
			}
		}
	}

	/**
	 * 根据属性和值获取信息
	 */
	@RequestMapping(value="findInvoicePropertyByName")
	public @ResponseBody Consignor findInvoicePropertyByName(HttpServletRequest request, HttpServletResponse response, Model model){
		String name = request.getParameter("name");
		String value = request.getParameter("propertyValue");
		Consignor feeConsignor = new Consignor();
		if(null!=name && name != "" && null!=value && value != ""){
			feeConsignor = consignorService.findUniqueByProperty(name,value);
		}
		return feeConsignor;
	}

	/**
	 * 应开发票引入明细时的确定按钮
	 */
	@RequestMapping(value = "addInvoice")
	public @ResponseBody
	String addInvoice(@RequestParam String ids, Model model, RedirectAttributes redirectAttributes, HttpServletRequest request) {
		List<Receivables> list = new ArrayList<Receivables>();
		if (StringUtils.isNotEmpty(ids)) {    //判断ids是否为空
			String[] _ids = ids.split(",");
			for (String id : _ids) {
				if (StringUtils.isNotEmpty(id)) {
					Receivables feeReceivables = receivablesService.get(id);
					list.add(feeReceivables);
				}
			}
		}
		return JsonMapper.toJsonString(list);
	}

	/**
	 * 修改状态
	 * @param id 应开发票id
	 * @param type 判断页面请求路径 form:跳转到form页面 list:跳转到list页面
	 * @return
	 */
	@RequestMapping(value = "updateStatus")
	public String updateStatus(String id,@RequestParam(value="type")String type) {
		if(StringUtils.isEmpty(id)){
			return "redirect:"+Global.getAdminPath()+"/fee/openInvoice/?repage";
		}
		//获得应开发票主表
		OpenInvoice feeOpenInvoice = openInvoiceService.get(id);
		//更新状态[核销金额  状态  应开发票id]
		if(feeOpenInvoice.getStatus() < feeOpenInvoice.updateStatus3){
			openInvoiceService.updateVcaMoneyAndStatusById(null,OpenInvoice.updateStatus3, id);
		}
		// 确认之后回填应收结算单
		List<OpenInvoiceDetail> list1 = openInvoiceDetailService.findOpenInvoiceMoney(id);
		for (int i = 0; i < list1.size(); i++) {
			OpenInvoiceDetail detail = list1.get(i);
			//获取应付结算单
			Receivables receivables = receivablesService.get(detail.getFeeReceivables().getId());
			//获取开票金额
			double invoiceMoney = detail.getInvoiceMoney();
			//获取结算金额
			double clearMoney = detail.getPayMoney();
			//System.out.println(invoiceMoney == clearMoney);
			if (receivables.getStatus() < Receivables.updateStatus4) {
				//判断开票金额是否等于结算金额
				if (invoiceMoney == clearMoney) {
					//更新应收结算单状态及开票金额【状态  开票金额  核销金额  未开票金额  未核销金额 id】
					receivablesService.updateStatusAndMoneyById(Receivables.updateStatus3, invoiceMoney,
							null, 0.0,clearMoney-(receivables.getVcaMoney()==null?0:receivables.getVcaMoney()), receivables.getId());
				} else {
					receivablesService.updateStatusAndMoneyById(Receivables.updateStatus2, invoiceMoney, null,
							clearMoney-invoiceMoney,clearMoney-(receivables.getVcaMoney()==null?0:receivables.getVcaMoney()), receivables.getId());
				}
			} else {
				receivablesService.updateStatusAndMoneyById(null, invoiceMoney, null, clearMoney-invoiceMoney, clearMoney-(receivables.getVcaMoney()==null?0:receivables.getVcaMoney()),receivables.getId());
			}
		}
		if(type.equals("form")){
			return "redirect:"+Global.getAdminPath()+"/fee/openInvoice/form?id="+id;
		}else{
			return "redirect:"+Global.getAdminPath()+"/fee/openInvoice/?repage";
		}
	}
	/**
	 * 修改状态
	 * @return
	 */
	@RequestMapping(value = "updateStatusTwo")
	public @ResponseBody AjaxJson updateStatusTwo(String ids) {
		AjaxJson j = new AjaxJson();
		String idArray[] =ids.split(",");
		for(String id : idArray) {
			//获得应开发票主表
			OpenInvoice feeOpenInvoice = openInvoiceService.get(id);
			//更新状态[核销金额  状态  应开发票id]
			if (feeOpenInvoice.getStatus() < feeOpenInvoice.updateStatus3) {
				openInvoiceService.updateVcaMoneyAndStatusById(null, OpenInvoice.updateStatus3, id);
			}
			// 确认之后回填应收结算单
			List<OpenInvoiceDetail> list1 = openInvoiceDetailService.findOpenInvoiceMoney(id);
			for (int i = 0; i < list1.size(); i++) {
				OpenInvoiceDetail detail = list1.get(i);
				//获取应付结算单
				Receivables receivables = receivablesService.get(detail.getFeeReceivables().getId());
				//获取开票金额
				double invoiceMoney = detail.getInvoiceMoney();
				//获取结算金额
				double clearMoney = detail.getPayMoney();
				//System.out.println(invoiceMoney == clearMoney);
				if (receivables.getStatus() < Receivables.updateStatus4) {
					//判断开票金额是否等于结算金额
					if (invoiceMoney == clearMoney) {
						//更新应收结算单状态及开票金额【状态  开票金额  核销金额  未开票金额  未核销金额 id】
						receivablesService.updateStatusAndMoneyById(Receivables.updateStatus3, invoiceMoney,
								null, 0.0, clearMoney - (receivables.getVcaMoney() == null ? 0 : receivables.getVcaMoney()), receivables.getId());
					} else {
						receivablesService.updateStatusAndMoneyById(Receivables.updateStatus2, invoiceMoney, null,
								clearMoney - invoiceMoney, clearMoney - (receivables.getVcaMoney() == null ? 0 : receivables.getVcaMoney()), receivables.getId());
					}
				} else {
					receivablesService.updateStatusAndMoneyById(null, invoiceMoney, null, clearMoney - invoiceMoney, clearMoney - (receivables.getVcaMoney() == null ? 0 : receivables.getVcaMoney()), receivables.getId());
				}
			}
		}
		j.setMsg("应开发票状态修改成功");
		return j;
	}

	/**
	 * 核销操作（跳转到新增收款单页面）
	 */
	@RequestMapping(value = "verificOperation")
	public String verificOperation(@RequestParam String ids, Model model, RedirectAttributes redirectAttributes, HttpServletRequest request) {
		// 如果ids为空，则跳转到feeOpenInvoice
		String url = "/fee/openInvoice/?repage";
		if (StringUtils.isNotEmpty(ids)) { // 判断ids是否为空
			String[] _ids = ids.split(",");
			List<OpenInvoiceDetail> list = new ArrayList<OpenInvoiceDetail>();
			for (String id : _ids) {
				if (StringUtils.isNotEmpty(id)) {
					OpenInvoiceDetail tempDetail = new OpenInvoiceDetail();
					OpenInvoice invoice = openInvoiceService.get(id);
					tempDetail.setFeeOpenInvoice(invoice);
					List<OpenInvoiceDetail> detail = openInvoiceDetailService.findList(tempDetail);
					list.addAll(detail);
					System.out.println(list);
				}
			}
			redirectAttributes.addFlashAttribute("list", list);
			redirectAttributes.addFlashAttribute("sign", "invoice");
			redirectAttributes.addFlashAttribute("ids", ids);
			redirectAttributes.addFlashAttribute("type", request.getParameter("type"));
			String target = request.getParameter("target")==null ? "invoice" : "billList";
			url = "/fee/bill/form?target="+target+"&ids="+ids;
		}
		return "redirect:" + Global.getAdminPath() + url;
	}

	/**
	 * 删除应开发票明细
	 * @param id 应开发票子表id
	 * @param redirectAttributes
	 * @return
	 */
	@RequestMapping(value = "removeOpenInvoiceDetail")
	public String removeOpenInvoiceDetail(String id, RedirectAttributes redirectAttributes) {
		OpenInvoiceDetail feeOpenInvoiceDetail = openInvoiceDetailService.get(id);	//根据id查询数据
		//获取本次开票金额
		Double detailInvMoney = feeOpenInvoiceDetail.getInvMoney();
		//根据发票子表的feePayInvoice的属性获取发票主表
		OpenInvoice feeOpenInvoice = openInvoiceService.get(feeOpenInvoiceDetail.getFeeOpenInvoice());
		//获取发票主表的开票金额
		Double invoiceMoney = feeOpenInvoice.getInvoiceMoney();
		//更新发票主表的开票金额[发票主表的总开票金额-发票子表的本次开票金额]
		if (null != detailInvMoney && null != invoiceMoney) {
			feeOpenInvoice.setInvoiceMoney((invoiceMoney-detailInvMoney));
			openInvoiceService.save(feeOpenInvoice);
		}
		openInvoiceDetailService.delete(feeOpenInvoiceDetail);
		addMessage(redirectAttributes, "删除应收发票明细成功");
		return "redirect:"+Global.getAdminPath()+"/fee/openInvoice/form?id="+feeOpenInvoice.getId();
	}



}